<template>
  <div class="validation-container">
    <!-- 页面头部 -->
    <el-header class="page-header">
      <div class="header-content">
        <h1>号码校验工具</h1>
        <div class="header-actions">
          <el-button type="text" @click="goToGenerator" :disabled="isOperationsDisabled">
            <el-icon>
              <Plus />
            </el-icon>
            号码生成
          </el-button>
          <el-button type="text" @click="handleLogout" :disabled="isOperationsDisabled">
            <el-icon>
              <SwitchButton />
            </el-icon>
            退出登录
          </el-button>
        </div>
      </div>
    </el-header>

    <!-- 主要内容区 -->
    <el-main class="main-content">
      <div class="main-content-inner">
        <!-- 文件上传区域 -->
        <el-card class="upload-card">
          <div class="upload-area" :class="{ 'upload-active': isDragging, 'disabled': isOperationsDisabled }">
            <el-upload ref="upload" class="upload-component" action="" :on-change="handleFileChange"
              :on-remove="handleFileRemove" :before-upload="beforeUpload" :auto-upload="false" :show-file-list="false"
              :on-drag-over="handleDragOver" :on-drag-leave="handleDragLeave" :on-drop="handleDrop"
              :disabled="isOperationsDisabled">
              <el-icon class="upload-icon">
                <UploadFilled />
              </el-icon>
              <div class="upload-text">
                <p>点击或拖拽文件至此处上传</p>
                <p class="upload-hint">支持 TXT、CSV、XLSX，文件将上传至服务端进行校验</p>
                <p class="upload-hint">小文件直接上传，较大文件自动分片上传</p>
              </div>
              <el-button type="primary" class="upload-button" :loading="isUploading" :disabled="isOperationsDisabled">
                {{ isUploading ? '上传中...' : '选择文件' }}
              </el-button>
            </el-upload>

            <!-- 已上传文件信息 -->
            <div v-if="uploadedFile" class="file-info">
              <el-tag closable @close="clearFile" size="large" :disabled="isOperationsDisabled">
                <div class="file-info-content">
                  <el-icon class="file-icon">
                    <Document />
                  </el-icon>
                  <span>{{ uploadedFile.name }}</span>
                  <span class="file-size">({{ formatFileSize(uploadedFile.size) }})</span>
                </div>
              </el-tag>
            </div>
          </div>
        </el-card>

        <!-- 服务端验证进度显示区域 -->
        <el-card class="progress-card" v-if="showProgress">
          <h3>服务端处理进度</h3>
          <el-progress :percentage="serverProgress"
            :status="serverProgress === 100 ? 'success' : 'active'"></el-progress>
          <div class="progress-info">
            <p>{{ serverStatusMessage }}</p>
            <p v-if="phoneCount > 0">共接收 {{ phoneCount }} 个号码</p>
          </div>
          <div style="margin-top: 10px; display: flex; gap: 12px; flex-wrap: wrap;">
            <el-button type="text" class="cancel-button" @click="cancelProcess" v-if="isProcessing">
              停止刷新
            </el-button>
            <el-button type="primary" @click="downloadResult('valid')" v-if="serverStatus === 'completed' && resultUrls.valid">
              下载有效
            </el-button>
            <el-button type="warning" @click="downloadResult('invalid')" v-if="serverStatus === 'completed' && resultUrls.invalid">
              下载无效
            </el-button>
            <el-button type="danger" @click="downloadResult('failed')" v-if="serverStatus === 'completed' && resultUrls.failed">
              下载失败
            </el-button>
          </div>
        </el-card>

        <!-- 结果显示区域（保留原表格，但默认不展示） -->
        <el-card class="results-card" v-if="showResults">

          <!-- 筛选和导出工具栏 -->
          <div class="toolbar">
            <div class="results-stats">
              <div class="results-stats-item">
                <span style="font-weight: bold;">总号码数：</span>
                <span style="color: #6b7280;">{{ totalNumbers }}</span>
              </div>
              <div class="results-stats-item">
                <span style="font-weight: bold;">待校验：</span>
                <span style="color: #f59e0b;">{{ pendingCount }}</span>
              </div>
              <div class="results-stats-item">
                <span style="font-weight: bold;">有效：</span>
                <span style="color: #10b981;">{{ successCount }}</span>
              </div>
              <div class="results-stats-item">
                <span style="font-weight: bold;">无效：</span>
                <span style="color: #ef4444;">{{ failCount }}</span>
              </div>
              <div class="results-stats-item">
                <span style="font-weight: bold;">接口失败：</span>
                <span style="color: #dc2626;">{{ apiErrorCount }}</span>
              </div>
            </div>
            <div class="filter-section">
              <el-select v-model="statusFilter" placeholder="状态筛选" clearable style="width: 140px; margin-right: 12px;">
                <el-option label="全部" value=""></el-option>
                <el-option label="待校验" value="pending"></el-option>
                <el-option label="有效" value="success"></el-option>
                <el-option label="无效" value="error"></el-option>
                <el-option label="接口校验失败" value="api_error"></el-option>
              </el-select>
              <el-button type="primary" @click="exportResults"
                :disabled="filteredResults.length === 0 || isOperationsDisabled">
                <el-icon>
                  <Download />
                </el-icon>
                导出结果
              </el-button>
            </div>
          </div>

          <el-table :data="currentPageFilteredData" border style="width: 100%; margin-top: 16px;">
            <el-table-column prop="number" label="号码" width="200"></el-table-column>
            <el-table-column prop="batch" label="批次" width="100"></el-table-column>
            <el-table-column prop="status" label="状态">
              <template #default="scope">
                <el-tag :type="getStatusType(scope.row.status)">
                  {{ getStatusText(scope.row.status) }}
                </el-tag>
              </template>
            </el-table-column>
          </el-table>

          <div class="pagination-container">
            <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
              :current-page="currentPage" :page-sizes="[10, 20, 50, 100]" :page-size="pageSize"
              layout="total, sizes, prev, pager, next, jumper" :total="filteredResults.length"></el-pagination>
          </div>
        </el-card>
      </div>
    </el-main>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import { showMessage, showNotification } from '@/utils/message'
import { logout } from '@/utils/auth'
import { UploadFilled, Document, SwitchButton, Download, Plus } from '@element-plus/icons-vue'
import axios from 'axios'
import * as XLSX from 'xlsx'

// 状态定义
const router = useRouter()
const upload = ref(null)
const uploadedFile = ref(null)
const isDragging = ref(false)
const isProcessing = ref(false)
const showProgress = ref(false)
const showResults = ref(false)
const progress = ref(0)
const totalNumbers = ref(0)
const processedNumbers = ref(0)
const totalRequests = ref(0)
const completedRequests = ref(0)
const results = ref([])
const cancelTokenSource = ref(null)
const currentPage = ref(1)
const pageSize = ref(20)
const statusFilter = ref('')
const isFileParsing = ref(false)
const isValidationRunning = ref(false)
// 新增：上传与服务端状态
const isUploading = ref(false)
const uploadId = ref('')
const serverStatus = ref('idle')
const serverProgress = ref(0)
const serverStatusMessage = ref('')
const resultUrl = ref('')
const resultUrls = ref({ valid: '', invalid: '', failed: '' })
const phoneCount = ref(0)
let statusTimer = null
let isPolling = false

// 计算属性 - 筛选后的数据
const filteredResults = computed(() => {
  if (!statusFilter.value) {
    return results.value
  }
  return results.value.filter(item => item.status === statusFilter.value)
})

// 计算属性 - 当前页数据（筛选后）
const currentPageFilteredData = computed(() => {
  const startIndex = (currentPage.value - 1) * pageSize.value
  const endIndex = startIndex + pageSize.value
  return filteredResults.value.slice(startIndex, endIndex)
})

// 计算属性 - 成功和失败数量
const successCount = computed(() => {
  return results.value.filter(item => item.status === 'success').length
})

const failCount = computed(() => {
  return results.value.filter(item => item.status === 'error').length
})

const apiErrorCount = computed(() => {
  return results.value.filter(item => item.status === 'api_error').length
})

const pendingCount = computed(() => {
  return results.value.filter(item => item.status === 'pending').length
})

// 计算属性 - 是否禁用操作按钮
const isOperationsDisabled = computed(() => {
  return isFileParsing.value || isValidationRunning.value || isUploading.value
})

// 状态处理方法
const getStatusType = (status) => {
  switch (status) {
    case 'success':
      return 'success'
    case 'error':
      return 'danger'
    case 'api_error':
      return 'danger'
    case 'pending':
      return 'warning'
    default:
      return 'info'
  }
}

const getStatusText = (status) => {
  switch (status) {
    case 'success':
      return '有效'
    case 'error':
      return '无效'
    case 'api_error':
      return '接口校验失败'
    case 'pending':
      return '待校验'
    default:
      return '未知'
  }
}

// 文件上传相关方法
const handleDragOver = () => {
  isDragging.value = true
}

const handleDragLeave = () => {
  isDragging.value = false
}

const handleDrop = (file) => {
  isDragging.value = false
  // 拖拽文件后直接开始解析
  if (file && file.raw && !isOperationsDisabled.value) {
    uploadedFile.value = file.raw
    startServerUpload()
  }
}

const beforeUpload = (file) => {
  // 检查文件类型
  const allowedTypes = [
    'text/plain', // txt
    'text/csv',   // csv
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // xlsx
    'application/vnd.ms-excel' // xls (虽然需求中没提，但这里也加上兼容)
  ]

  if (!allowedTypes.includes(file.type)) {
    showMessage.error('请上传 TXT、CSV 或 XLSX 格式的文件')
    return false
  }

  return true
}

const handleFileChange = (file) => {
  if (isOperationsDisabled.value) {
    return
  }
  uploadedFile.value = file.raw
  // 改为上传到服务端
  startServerUpload()
}

const handleFileRemove = () => {
  uploadedFile.value = null
  results.value = []
  showResults.value = false
  totalNumbers.value = 0
  processedNumbers.value = 0
  uploadId.value = ''
  serverStatus.value = 'idle'
  serverProgress.value = 0
  serverStatusMessage.value = ''
  resultUrl.value = ''
  resultUrls.value = { valid: '', invalid: '', failed: '' }
}

const clearFile = () => {
  if (isOperationsDisabled.value) {
    return
  }
  uploadedFile.value = null
  results.value = []
  showResults.value = false
  totalNumbers.value = 0
  processedNumbers.value = 0
  if (upload.value) {
    upload.value.clearFiles()
  }
  uploadId.value = ''
  serverStatus.value = 'idle'
  serverProgress.value = 0
  serverStatusMessage.value = ''
  resultUrl.value = ''
  resultUrls.value = { valid: '', invalid: '', failed: '' }
}

// 格式化文件大小显示
const formatFileSize = (size) => {
  if (size < 1024) {
    return `${size} B`
  } else if (size < 1024 * 1024) {
    return `${(size / 1024).toFixed(2)} KB`
  } else {
    return `${(size / (1024 * 1024)).toFixed(2)} MB`
  }
}

// 处理文件解析（保留：用于本地解析导出等，不再触发服务端校验）
const processFile = async () => {
  if (!uploadedFile.value) {
    return
  }

  console.log('开始处理文件:', uploadedFile.value.name) // 调试信息

  try {
    isFileParsing.value = true
    isProcessing.value = true
    showProgress.value = false
    progress.value = 0

    // 解析文件获取号码
    const numbers = await parseFile(uploadedFile.value)


    if (numbers.length === 0) {
      showMessage.warning('未从文件中解析到任何号码，保持之前的结果')
      // 保持之前的结果，不清空
      return
    }

    // 格式化号码，确保以+91开头
    const formattedNumbers = formatNumbers(numbers)

    // 去重处理
    const uniqueNumbers = [...new Set(formattedNumbers)]

    totalNumbers.value = uniqueNumbers.length
    processedNumbers.value = 0

    // 直接将号码添加到结果表格中，状态为"待校验"
    results.value = uniqueNumbers.map((number, index) => ({
      number,
      status: 'pending',
      batch: Math.floor(index / 500) + 1 // 每500个号码为一个批次
    }))

    // 显示结果表格
    showResults.value = true

    showMessage.success(`成功解析到 ${totalNumbers.value} 个号码，已添加到校验列表`)
  } catch (error) {
    showMessage.error(`文件解析失败: ${error.message || '未知错误'}，保持之前的结果`)
    // 保持之前的结果，不清空
    console.error('文件解析错误:', error) // 调试信息
  } finally {
    isFileParsing.value = false
    isProcessing.value = false
  }
}

// 新流程：将文件上传至服务端并轮询状态
const startServerUpload = async () => {
  if (!uploadedFile.value) return
  try {
    isUploading.value = true
    isProcessing.value = true
    showProgress.value = true
    serverProgress.value = 0
    serverStatus.value = 'uploading'
    serverStatusMessage.value = '正在上传文件…'

    const bigFileThreshold = 5 * 1024 * 1024 // 5MB
    const maxConcurrency = 6

    if (uploadedFile.value.size <= bigFileThreshold) {
      await directUpload(uploadedFile.value, maxConcurrency)
    } else {
      await chunkedUpload(uploadedFile.value, maxConcurrency)
    }

    beginStatusPolling()
  } catch (error) {
    showMessage.error(error.message || '上传失败')
    resetProcessingState()
  }
}

const directUpload = async (file, maxConcurrency) => {
  const form = new FormData()
  form.append('file', file)
  const resp = await axios.post('/api/uploads/direct', form, {
    headers: { 'Content-Type': 'multipart/form-data' },
  })
  if (!resp.data || resp.data.success !== true) throw new Error('直传失败')
  uploadId.value = resp.data.uploadId
  phoneCount.value = resp.data.phoneCount || 0
  serverStatusMessage.value = resp.data.message || '文件上传成功'
}

const chunkedUpload = async (file, maxConcurrency) => {
  const chunkSize = 2 * 1024 * 1024 // 2MB
  const totalChunks = Math.ceil(file.size / chunkSize)
  const initResp = await axios.post('/api/uploads/chunk/init', {
    filename: file.name,
    totalSize: file.size,
    totalChunks,
  })
  if (!initResp.data || initResp.data.success !== true) throw new Error('分片初始化失败')
  const id = initResp.data.uploadId
  uploadId.value = id
  phoneCount.value = 0

  let current = 0
  const uploadOne = async (index) => {
    const start = index * chunkSize
    const end = Math.min(file.size, start + chunkSize)
    const blob = file.slice(start, end)
    const form = new FormData()
    form.append('uploadId', id)
    form.append('chunkIndex', String(index))
    form.append('chunk', blob)
    await axios.post('/api/uploads/chunk/upload', form, {
      headers: { 'Content-Type': 'multipart/form-data' },
    })
    current++
    serverProgress.value = Math.round((current / totalChunks) * 100)
  }

  const queue = Array.from({ length: totalChunks }, (_, i) => i)
  const workers = Math.min(maxConcurrency, totalChunks)
  const runNext = async () => {
    const idx = queue.shift()
    if (idx === undefined) return
    await uploadOne(idx)
    await runNext()
  }
  await Promise.all(Array.from({ length: workers }, runNext))

  const completeResp = await axios.post('/api/uploads/chunk/complete', {
    uploadId: id,
    filename: file.name,
    totalChunks
  })
  if (!completeResp.data || completeResp.data.success !== true) throw new Error('分片合并失败')
  serverStatusMessage.value = completeResp.data.message || '文件上传成功，正在验证手机号码'
  phoneCount.value = completeResp.data.phoneCount || 0
}

const beginStatusPolling = () => {
  if (!uploadId.value) return
  serverStatus.value = 'processing'
  serverStatusMessage.value = '服务器正在验证号码…'
  if (statusTimer) {
    clearTimeout(statusTimer)
    statusTimer = null
  }
  isPolling = true
  // 立即执行一次，后续由 checkUploadStatus 在请求完成后再调度
  checkUploadStatus()
}

const checkUploadStatus = async () => {
  try {
    const resp = await axios.get(`/api/uploads/status/${uploadId.value}`)
    if (!resp.data || resp.data.success !== true) return
    const status = resp.data
    serverStatus.value = status.status
    serverProgress.value = Math.round(status.progress || 0)
    resultUrl.value = status.resultUrl || ''
    if (status.resultUrls && typeof status.resultUrls === 'object') {
      resultUrls.value = {
        valid: status.resultUrls.valid || '',
        invalid: status.resultUrls.invalid || '',
        failed: status.resultUrls.failed || ''
      }
    } else {
      resultUrls.value = { valid: '', invalid: '', failed: '' }
    }
    serverStatusMessage.value = status.message || ''
    if (status.status === 'completed') {
      if (statusTimer) {
        clearTimeout(statusTimer)
        statusTimer = null
      }
      isPolling = false
      isProcessing.value = false
      isUploading.value = false
      showNotification.success({ title: '校验完成', message: '结果已生成，可下载' })
      return
    }
  } catch (e) {
    // 忽略短暂错误
  }
  // 仅在上一轮完成后再调度下一轮
  if (isPolling) {
    statusTimer = setTimeout(checkUploadStatus, 2000)
  }
}

const downloadResult = (type) => {
  // 兼容旧的单一 resultUrl
  if (!type) {
    if (!resultUrl.value) return
    window.open(resultUrl.value, '_blank')
    return
  }
  const urlMap = resultUrls.value || {}
  const url = urlMap[type]
  if (!url) return
  window.open(url, '_blank')
}

// 开始校验号码
const startValidation = async () => {
  if (pendingCount.value === 0) {
    showMessage.warning('没有待校验的号码')
    return
  }

  try {
    isValidationRunning.value = true
    isProcessing.value = true
    showProgress.value = true
    progress.value = 0
    processedNumbers.value = 0

    // 获取所有待校验的号码
    const pendingNumbers = results.value
      .filter(item => item.status === 'pending')
      .map(item => item.number)

    totalNumbers.value = pendingNumbers.length
    processedNumbers.value = 0

    showMessage.success(`开始校验 ${totalNumbers.value} 个号码`)

    // 批量调用API验证号码
    await validateNumbersInBatches(pendingNumbers)

    // 全部完成后显示结果
    showNotification.success({
      title: '校验完成',
      message: `共校验 ${totalNumbers.value} 个号码，成功 ${successCount.value} 个，失败 ${failCount.value} 个`,
      duration: 5000
    })
  } catch (error) {
    if (error.message !== '取消处理') {
      showMessage.error(`校验失败: ${error.message || '未知错误'}`)
    }
  } finally {
    isValidationRunning.value = false
    resetProcessingState()
  }
}

// 解析不同类型的文件
const parseFile = (file) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    const fileName = file.name.toLowerCase()

    reader.onload = (e) => {
      try {
        let numbers = []

        if (fileName.endsWith('.txt')) {
          // 处理TXT文件
          const content = e.target.result
          const lines = content.split(/\r?\n/)
          lines.forEach(line => {
            if (line.trim()) {
              // 提取可能的号码
              const potentialNumbers = line.match(/[+]?\d+/g)
              if (potentialNumbers) {
                numbers = [...numbers, ...potentialNumbers]
              }
            }
          })
        } else if (fileName.endsWith('.csv')) {
          // 处理CSV文件
          const content = e.target.result
          const lines = content.split(/\r?\n/)

          lines.forEach((line, index) => {
            if (line.trim() && index > 0) { // 跳过标题行
              // 解析CSV行，处理引号和逗号
              const columns = parseCSVLine(line)
              if (columns.length > 0) {
                // 只取第一列作为电话号码
                const phoneColumn = columns[0].trim()
                if (phoneColumn) {
                  // 提取完整的电话号码（以+开头的完整号码）
                  const phoneMatch = phoneColumn.match(/^\+?\d{10,}$/)
                  if (phoneMatch) {
                    numbers.push(phoneMatch[0])
                  }
                }
              }
            }
          })
        } else if (fileName.endsWith('.xlsx') || fileName.endsWith('.xls')) {
          // 处理Excel文件：遍历所有工作表，按二维数组提取每个单元格
          const data = new Uint8Array(e.target.result)
          const workbook = XLSX.read(data, { type: 'array' })

          workbook.SheetNames.forEach(sheetName => {
            const worksheet = workbook.Sheets[sheetName]
            // 使用 header:1 生成二维数组，每个单元格更易逐一处理；raw:false 让数字以文本呈现
            const rows = XLSX.utils.sheet_to_json(worksheet, { header: 1, raw: false, defval: '' })
            rows.forEach(rowArray => {
              if (Array.isArray(rowArray)) {
                rowArray.forEach(cellValue => {
                  if (cellValue === null || cellValue === undefined) return
                  const text = String(cellValue)
                  const potentialNumbers = text.match(/[+]?\d+/g)
                  if (potentialNumbers) {
                    numbers = [...numbers, ...potentialNumbers]
                  }
                })
              }
            })
          })
        }

        resolve(numbers)
      } catch (error) {
        reject(new Error(`文件解析错误: ${error.message}`))
      }
    }

    reader.onerror = () => {
      reject(new Error('文件读取失败'))
    }

    if (fileName.endsWith('.xlsx') || fileName.endsWith('.xls')) {
      reader.readAsArrayBuffer(file)
    } else {
      reader.readAsText(file)
    }
  })
}

// 格式化号码，确保以+91开头
const formatNumbers = (numbers) => {
  return numbers.map(number => {
    // 移除所有非数字字符
    let cleaned = number.replace(/\D/g, '')

    // 确保以+91开头
    if (cleaned.startsWith('91')) {
      return `+${cleaned}`
    } else if (!cleaned.startsWith('+91')) {
      return `+91${cleaned}`
    }

    return number
  })
}

// 批量验证号码，遵守API限制
const validateNumbersInBatches = (numbers) => {
  return new Promise((resolve, reject) => {
    // 每个请求最多500个号码
    const batchSize = 500
    // 分成多个批次
    const batches = []
    for (let i = 0; i < numbers.length; i += batchSize) {
      batches.push(numbers.slice(i, i + batchSize))
    }

    totalRequests.value = batches.length
    completedRequests.value = 0

    // 并发控制，最多100个并发请求
    const concurrency = 6
    let currentBatch = 0
    let isCancelled = false

    // 创建取消令牌
    cancelTokenSource.value = axios.CancelToken.source()

    // 处理单个批次
    const processBatch = async (batchIndex) => {
      if (isCancelled) return

      try {
        const batchNumbers = batches[batchIndex]
        const response = await axios.post(
          '/numberscore/lookup_ori_phone/batch',
          { phones: batchNumbers },
          {
            headers: {
              'Content-Type': 'application/json'
            }
          }
        )

        if (response.data.status === 200 && response.data.data) {
          // 处理返回结果，更新现有结果
          // 接口结构：{"data":{"+919115286778":{}},"info":"success","status":200}
          // 如果手机号码在data里，就证明校验成功
          const validNumberSet = new Set(Object.keys(response.data.data))

          batchNumbers.forEach((number, idx) => {
            const existingIndex = batchIndex * batchSize + idx
            if (validNumberSet.has(number)) {
              results.value[existingIndex].status = 'success'
            } else {
              results.value[existingIndex].status = 'error'
            }
          })
          processedNumbers.value += batchNumbers.length
        } else {
          // 处理API返回错误，更新现有结果
          batchNumbers.forEach((number, idx) => {
            const existingIndex = batchIndex * batchSize + idx
            if (existingIndex !== -1) {
              results.value[existingIndex].status = 'api_error'
            }
          })
          processedNumbers.value += batchNumbers.length
          showMessage.warning(`批次 ${batchIndex + 1} 处理失败: ${response.data.info || '未知错误'}`)
        }
      } catch (error) {
        if (axios.isCancel(error)) {
          // 请求被取消
          return
        }

        // 处理请求错误，更新现有结果
        batches[batchIndex].forEach((number, idx) => {
          const existingIndex = batchIndex * batchSize + idx
          if (existingIndex !== -1) {
            results.value[existingIndex].status = 'api_error'
          }
        })
        processedNumbers.value += batches[batchIndex].length
        showMessage.error(`批次 ${batchIndex + 1} 请求失败: ${error.message}`)
      } finally {
        if (isCancelled) return

        completedRequests.value++
        // 更新进度
        progress.value = Math.round((completedRequests.value / totalRequests.value) * 100)

        // 处理下一个批次
        if (currentBatch < batches.length) {
          processBatch(currentBatch++).then(() => {
            if (completedRequests.value === totalRequests.value) {
              resolve()
            }
          }).catch(reject)
        }
      }
    }

    // 启动并发请求
    for (let i = 0; i < Math.min(concurrency, batches.length); i++) {
      if (currentBatch < batches.length) {
        processBatch(currentBatch++).then(() => {
          if (completedRequests.value === totalRequests.value) {
            resolve()
          }
        }).catch(reject)
      }
    }

    // 取消处理的方法
    window.cancelValidation = () => {
      isCancelled = true
      if (cancelTokenSource.value) {
        cancelTokenSource.value.cancel('取消处理')
      }
      reject(new Error('取消处理'))
    }
  })
}

// 取消处理：仅停止轮询刷新
const cancelProcess = () => {
  isPolling = false
  if (statusTimer) {
    clearTimeout(statusTimer)
    statusTimer = null
  }
  showMessage.info('已停止刷新')
}

// 解析CSV行
const parseCSVLine = (line) => {
  const result = []
  let current = ''
  let inQuotes = false

  for (let i = 0; i < line.length; i++) {
    const char = line[i]

    if (char === '"') {
      inQuotes = !inQuotes
    } else if (char === ',' && !inQuotes) {
      result.push(current.trim())
      current = ''
    } else {
      current += char
    }
  }

  result.push(current.trim())
  return result
}

// 重新处理文件（当编码改变时）
const reprocessFile = () => {
  if (uploadedFile.value && uploadedFile.value.name.toLowerCase().endsWith('.csv')) {
    processFile()
  }
}

// 重置处理状态
const resetProcessingState = () => {
  isProcessing.value = false
  isValidationRunning.value = false
  isUploading.value = false
  showProgress.value = false
  progress.value = 0
  cancelTokenSource.value = null
  isPolling = false
  if (statusTimer) {
    clearTimeout(statusTimer)
    statusTimer = null
  }
}

// 导出结果
const exportResults = async () => {
  if (isOperationsDisabled.value) {
    return
  }
  if (filteredResults.value.length === 0) {
    showMessage.warning('没有数据可导出')
    return
  }

  try {

    // 准备导出数据
    const exportData = filteredResults.value.map(item => ({
      '号码': item.number,
      '批次': item.batch || '',
      '状态': getStatusText(item.status)
    }))

    // 创建工作簿
    const workbook = XLSX.utils.book_new()
    const worksheet = XLSX.utils.json_to_sheet(exportData)

    // 设置列宽
    const colWidths = [
      { wch: 20 }, // 号码列
      { wch: 10 }, // 批次列
      { wch: 10 }  // 状态列
    ]
    worksheet['!cols'] = colWidths

    // 添加工作表到工作簿
    XLSX.utils.book_append_sheet(workbook, worksheet, '验证结果')

    // 生成文件名
    const now = new Date()
    const dateStr = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}`
    const timeStr = `${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}`
    const fileName = `号码验证结果_${dateStr}_${timeStr}.xlsx`

    // 导出文件
    XLSX.writeFile(workbook, fileName)
    showMessage.success(`已导出 ${exportData.length} 条记录到 ${fileName}`)
  } catch (error) {
    showMessage.error(`导出失败: ${error.message}`)
  }
}

// 分页相关方法
const handleSizeChange = (val) => {
  pageSize.value = val
  currentPage.value = 1
}

const handleCurrentChange = (val) => {
  currentPage.value = val
}

// 跳转到生成器页面
const goToGenerator = () => {
  if (isOperationsDisabled.value) {
    return
  }
  router.push('/generator')
}

// 退出登录
const handleLogout = () => {
  if (isOperationsDisabled.value) {
    return
  }
  logout()
  router.push('/login')
  showMessage.success('已退出登录')
}

// 页面挂载时不需要检查登录状态
onMounted(() => {
  // 移除登录状态检查
})
</script>

<style scoped>
.validation-container {
  /* display: flex;
  flex-direction: column; */
  min-height: 100vh;
  background-color: #f9fafb;
}

.page-header {
  background-color: #ffffff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  padding: 0;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  height: 60px;
}

.header-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 20px;
  height: 100%;
}

.header-actions {
  display: flex;
  gap: 12px;
}

.header-content h1 {
  margin: 0;
  font-size: 18px;
  color: #1f2329;
}

.main-content {
  flex: 1;
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
  width: 100%;
  margin-top: 60px;
}

.main-content-inner {
  height: 100%;
  overflow: auto;
}

.upload-card,
.progress-card,
.results-card {
  margin-bottom: 20px;
  border-radius: 8px;
  border: 1px solid #e5e7eb;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.upload-area {
  border: 2px dashed #d1d5db;
  border-radius: 8px;
  padding: 40px 20px;
  text-align: center;
  transition: all 0.3s ease;
  margin: 20px;
}

.upload-area.upload-active {
  border-color: #4096ff;
  background-color: rgba(64, 150, 255, 0.05);
}

.upload-icon {
  font-size: 48px;
  color: #9ca3af;
  margin-bottom: 16px;
}

.upload-text {
  margin: 0 10px 20px;
}

.upload-text p {
  margin: 0 0 8px 0;
  color: #4b5563;
}

.upload-hint {
  font-size: 14px;
  color: #9ca3af;
}

.file-info {
  margin-top: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}

.file-info-content {
  display: flex;
  align-items: center;
  gap: 6px;
}

.file-icon {
  margin-right: 6px;
}

.file-size {
  font-size: 12px;
  color: #9ca3af;
  margin-left: 6px;
}

.encoding-settings {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  padding: 8px 12px;
  background-color: #f8fafc;
  border-radius: 6px;
  border: 1px solid #e2e8f0;
}

.encoding-label {
  font-size: 14px;
  color: #64748b;
  font-weight: 500;
}


.progress-info {
  display: flex;
  justify-content: space-between;
  margin-top: 12px;
  color: #6b7280;
  font-size: 14px;
}

.cancel-button {
  color: #ef4444;
  margin-top: 10px;
}

.results-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
}

.results-stats {
  display: flex;
  gap: 20px;
}

.stat-item {
  min-width: 120px;
}

.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 12px;
  border-bottom: 1px solid #e5e7eb;
}

.filter-section {
  display: flex;
  align-items: center;
}

.filter-info {
  color: #6b7280;
  font-size: 14px;
}

.pagination-container {
  margin-top: 20px;
  text-align: right;
}

.upload-area.disabled {
  opacity: 0.6;
  pointer-events: none;
}

/* 移除重复样式，使用全局样式 */
</style>